import sys
import os
import shutil
import sqlite3
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *


class Database:
    def __init__(self):
        self.conn = sqlite3.connect('icecream.db')
        self.create_table()  # 确保 products 表被创建
        self.create_tables()  # 修改：调用 create_tables 方法
        self.create_discount_table()
        self.initialize_default_discounts()

    def create_tables(self):  # 新增：创建 sales 和 sale_items 表
        self.conn.execute('''CREATE TABLE IF NOT EXISTS sales
             (ID INTEGER PRIMARY KEY AUTOINCREMENT,
             TOTAL REAL NOT NULL,
             DISCOUNTED_TOTAL REAL NOT NULL,
             TIMESTAMP DATETIME DEFAULT CURRENT_TIMESTAMP);''')
        self.conn.execute('''CREATE TABLE IF NOT EXISTS sale_items
             (ID INTEGER PRIMARY KEY AUTOINCREMENT,
             SALE_ID INTEGER NOT NULL,
             PRODUCT_ID INTEGER NOT NULL,
             QUANTITY INTEGER NOT NULL,
             FOREIGN KEY (SALE_ID) REFERENCES sales (ID),
             FOREIGN KEY (PRODUCT_ID) REFERENCES products (ID));''')
        self.conn.commit()

    def create_table(self):
        self.conn.execute('''CREATE TABLE IF NOT EXISTS products
             (ID INTEGER PRIMARY KEY AUTOINCREMENT,
             NAME TEXT NOT NULL,
             PRICE REAL NOT NULL,
             STOCK INTEGER NOT NULL,
             IMAGE_PATH TEXT);''')
        self.conn.commit()

    def create_discount_table(self):
        self.conn.execute('''CREATE TABLE IF NOT EXISTS discounts
             (THRESHOLD INTEGER PRIMARY KEY,
             RATE REAL NOT NULL);''')
        self.conn.commit()

    def initialize_default_discounts(self):
        default_discounts = [
            (5, 0.9),  # 5个及以上商品，9折
            (10, 0.8)  # 10个及以上商品，8折
        ]
        cursor = self.conn.cursor()
        cursor.executemany("INSERT OR IGNORE INTO discounts (THRESHOLD, RATE) VALUES (?, ?)", default_discounts)
        self.conn.commit()

    def get_discounts(self):
        query = "SELECT * FROM discounts ORDER BY THRESHOLD DESC"
        return self.execute_query(query).fetchall()

    def update_discount(self, threshold, rate):
        query = "INSERT OR REPLACE INTO discounts (THRESHOLD, RATE) VALUES (?, ?)"
        self.execute_query(query, (threshold, rate))

    def execute_query(self, query, params=()):
        cursor = self.conn.cursor()
        cursor.execute(query, params)
        self.conn.commit()
        return cursor

    def get_product(self, product_id):
        query = "SELECT * FROM products WHERE ID = ?"
        return self.execute_query(query, (product_id,)).fetchone()


class ProductManager(QWidget):
    def __init__(self):
        super().__init__()
        self.db = Database()
        self.init_ui()
        self.load_data()

    def load_data(self):
        query = "SELECT * FROM products"
        results = self.db.execute_query(query).fetchall()
        self.table.setRowCount(len(results))
        for row, product in enumerate(results):
            for col, data in enumerate(product):
                self.table.setItem(row, col, QTableWidgetItem(str(data)))

    def add_product(self):
        name = self.name_input.text()
        price = self.price_input.value()
        stock = self.stock_input.value()
        image_path = self.image_path.text()
        self.db.execute_query(
            "INSERT INTO products (NAME, PRICE, STOCK, IMAGE_PATH) VALUES (?, ?, ?, ?)",
            (name, price, stock, image_path)
        )
        self.load_data()

    def update_product(self):
        selected_row = self.table.currentRow()
        if selected_row >= 0:
            product_id = self.table.item(selected_row, 0).text()
            name = self.name_input.text()
            price = self.price_input.value()
            stock = self.stock_input.value()
            image_path = self.image_path.text()
            self.db.execute_query(
                "UPDATE products SET NAME = ?, PRICE = ?, STOCK = ?, IMAGE_PATH = ? WHERE ID = ?",
                (name, price, stock, image_path, product_id)
            )
            self.load_data()

    def delete_product(self):
        selected_row = self.table.currentRow()
        if selected_row >= 0:
            product_id = self.table.item(selected_row, 0).text()
            self.db.execute_query("DELETE FROM products WHERE ID = ?", (product_id,))
            self.load_data()

    def load_selected_product(self, row, column):
        product_id = self.table.item(row, 0).text()
        product = self.db.get_product(product_id)
        self.name_input.setText(product[1])
        self.price_input.setValue(product[2])
        self.stock_input.setValue(product[3])
        self.image_path.setText(product[4])

    def browse_image(self):
        file_name, _ = QFileDialog.getOpenFileName(self, '选择图片', '', 'Image files (*.jpg *.png)')
        if file_name:
            # 获取 images 文件夹的路径
            if getattr(sys, 'frozen', False):
                # 如果是打包后的 exe，使用 sys._MEIPASS 获取资源路径
                base_path = sys._MEIPASS
            else:
                # 如果是开发环境，使用当前文件所在目录
                base_path = os.path.dirname(os.path.abspath(__file__))  # 修改：确保使用项目代码的绝对路径
            
            # 修改：确保 images 目录始终相对于 exe 根路径创建
            image_dir = os.path.join(os.path.dirname(sys.executable), 'images')
            if not os.path.exists(image_dir):
                os.makedirs(image_dir)
                print(f'创建目录: {image_dir}')
            
            image_name = os.path.basename(file_name)
            dest_path = os.path.join(image_dir, image_name)
            
            # 修改：使用 shutil.copy2 支持跨盘符复制
            shutil.copy2(file_name, dest_path)  # 替换原有的 shutil.copy
            self.image_path.setText(f'images/{image_name}')


    def init_ui(self):
        self.setWindowTitle('商品管理')
        self.setGeometry(300, 300, 600, 400)

        layout = QVBoxLayout()

        # 输入表单
        form_layout = QFormLayout()
        self.name_input = QLineEdit()
        self.price_input = QDoubleSpinBox()
        self.price_input.setMaximum(9999)
        self.stock_input = QSpinBox()
        self.stock_input.setValue(100)
        self.stock_input.setMaximum(9999)
        self.image_path = QLineEdit()
        btn_browse = QPushButton('浏览...')
        btn_browse.clicked.connect(self.browse_image)

        form_layout.addRow('商品名称:', self.name_input)
        form_layout.addRow('价格:', self.price_input)
        form_layout.addRow('库存:', self.stock_input)
        form_layout.addRow('图片路径:', self.image_path)
        form_layout.addRow(btn_browse)

        # 操作按钮
        btn_layout = QHBoxLayout()
        btn_add = QPushButton('新增')
        btn_add.clicked.connect(self.add_product)
        btn_update = QPushButton('更新')
        btn_update.clicked.connect(self.update_product)
        btn_delete = QPushButton('删除')
        btn_delete.clicked.connect(self.delete_product)

        btn_layout.addWidget(btn_add)
        btn_layout.addWidget(btn_update)
        btn_layout.addWidget(btn_delete)

        # 商品列表
        self.table = QTableWidget()
        self.table.setColumnCount(5)
        self.table.setHorizontalHeaderLabels(['ID', '名称', '价格', '库存', '图片路径'])
        self.table.cellDoubleClicked.connect(self.load_selected_product)

        layout.addLayout(form_layout)
        layout.addLayout(btn_layout)
        layout.addWidget(self.table)
        self.setLayout(layout)


class PosSystem(QWidget):
    def __init__(self):
        super().__init__()
        self.db = Database()
        self.cart = {}
        self.discount_rules = {}  # 动态折扣规则
        self.main_layout = QVBoxLayout()  # 初始化 main_layout 为类属性
        self.init_ui()
        self.load_products()
        self.load_discounts()  # 新增：加载折扣规则

    def load_discounts(self):  # 新增：从数据库加载折扣规则
        discounts = self.db.get_discounts()
        self.discount_rules = {int(d[0]): float(d[1]) for d in discounts}
        self.update_discount_label()

    def update_discount_label(self):  # 新增：更新折扣标签
        discount_str = ', '.join([f"{k}:{v}" for k, v in self.discount_rules.items()])
        self.discount_label.setText(f"当前折扣规则：{discount_str}")

    def load_products(self):
        query = "SELECT * FROM products ORDER BY NAME"  # 按产品名称排序
        results = self.db.execute_query(query).fetchall()
        
        # 检查 self.products_layout 是否已存在，如果存在则清空内容
        if hasattr(self, 'products_layout'):
            while self.products_layout.count():
                child = self.products_layout.takeAt(0)
                if child.widget():
                    child.widget().deleteLater()
        else:
            self.products_layout = QGridLayout()  # 如果不存在则创建新的布局
        
        # 动态计算每行展示的商品数量
        window_width = self.width()
        item_width = 180  # 每个商品项的宽度（包括图片和信息）
        items_per_row = max(1, window_width // item_width)  # 至少展示1个商品
        
        for idx, product in enumerate(results):
            item_widget = self.create_product_item(product)
            row = idx // items_per_row  # 动态计算行数
            col = idx % items_per_row
            self.products_layout.addWidget(item_widget, row, col)
    
        # 使用 QScrollArea 包裹商品列表区域
        scroll_area = QScrollArea()
        scroll_area.setWidgetResizable(True)
        container = QWidget()  # 新增：创建一个容器来包裹 QGridLayout
        container.setLayout(self.products_layout)
        scroll_area.setWidget(container)
        
        # 新增：设置 scroll_area 的最小高度
        scroll_area.setMinimumHeight(600)  # 增加展示高度

        # 替换原有的商品列表布局
        if hasattr(self, 'scroll_area'):  # 检查是否已经存在 scroll_area
            self.main_layout.removeWidget(self.scroll_area)
            self.scroll_area.deleteLater()
        
        # 将 scroll_area 放到最上面
        self.main_layout.insertWidget(0, scroll_area)  # 修改：使用 insertWidget 方法将 scroll_area 放到最上面
        self.scroll_area = scroll_area  # 保存 scroll_area 引用

    def create_product_item(self, product):
        widget = QWidget()
        layout = QVBoxLayout()

        # 显示图片
        lbl_image = QLabel()
        pixmap = QPixmap(product[4])
        lbl_image.setPixmap(pixmap.scaled(150, 150, Qt.KeepAspectRatio))  # 增大图片尺寸

        # 显示信息
        lbl_name = QLabel(product[1])
        lbl_price = QLabel(f'￥{product[2]}')
        spinbox = QSpinBox()
        spinbox.setMaximum(product[3])
        spinbox.setFixedHeight(30)  # 设置高度
        spinbox.setFixedWidth(60)   # 设置宽度
        spinbox.valueChanged.connect(lambda v, p=product: self.update_cart(p[0], v))

        layout.addWidget(lbl_image)
        layout.addWidget(lbl_name)
        layout.addWidget(lbl_price)
        layout.addWidget(spinbox)
        widget.setLayout(layout)
        return widget

    def update_cart(self, product_id, quantity):
        if quantity > 0:
            self.cart[product_id] = quantity
        else:
            if product_id in self.cart:
                del self.cart[product_id]
        self.update_cart_display()

    def update_cart_display(self):
        self.cart_table.setRowCount(len(self.cart))
        for row, (pid, qty) in enumerate(self.cart.items()):
            product = self.db.get_product(pid)
            self.cart_table.setItem(row, 0, QTableWidgetItem(product[1]))
            self.cart_table.setItem(row, 1, QTableWidgetItem(str(product[2])))
            self.cart_table.setItem(row, 2, QTableWidgetItem(str(qty)))
            self.cart_table.setItem(row, 3, QTableWidgetItem(f"{product[2] * qty:.2f}"))
        self.calculate_total()

        # 新增：计算并显示总数量
        total_quantity = sum(self.cart.values())
        self.total_quantity_label.setText(f"总数量：{total_quantity}")

    def calculate_total(self):
        total = sum([self.db.get_product(pid)[2] * qty for pid, qty in self.cart.items()])
        total_qty = sum(self.cart.values())

        discount = 1.0
        discount_description = "无折扣"  # 默认折扣描述
        for threshold in sorted(self.discount_rules.keys(), reverse=True):
            if total_qty >= threshold:
                discount = self.discount_rules[threshold]
                discount_description = f"{threshold}个及以上商品，{int(discount * 10)}折"  # 正确计算折扣描述
                break

        discount_total = total * discount

        # 修改：将折扣价部分单独封装为 QLabel 并设置样式
        self.total_label.setText(f"总价：{total:.2f}")
        
        # 新增：创建折扣价标签并添加到布局中
        discount_price_label = QLabel(f"{discount_description}，{discount_total:.2f}")
        discount_price_label.setStyleSheet("color: red; font-weight: bold;")
        
        # 确保 discount_label 是一个带有布局的容器
        if not hasattr(self, 'discount_container'):
            self.discount_container = QWidget()
            self.discount_layout = QHBoxLayout()
            self.discount_container.setLayout(self.discount_layout)
            self.main_layout.replaceWidget(self.discount_label, self.discount_container)  # 替换原有的 discount_label
            self.discount_label.deleteLater()  # 删除原有的 discount_label
            self.discount_label = self.discount_container  # 更新引用

        # 清空布局并添加新的折扣价标签
        while self.discount_layout.count():
            item = self.discount_layout.takeAt(0)
            widget = item.widget()
            if widget:
                widget.deleteLater()
        self.discount_layout.addWidget(discount_price_label)

    def clear_cart(self):
        self.cart = {}  # 清空购物车
        self.update_cart_display()

        # 新增：重置商品列表中每个商品的数量选择框
        for row in range(self.products_layout.rowCount()):
            for col in range(self.products_layout.columnCount()):
                item = self.products_layout.itemAtPosition(row, col)
                if item:
                    widget = item.widget()
                    if isinstance(widget, QWidget):
                        layout = widget.layout()
                        if layout:
                            for i in range(layout.count()):
                                child = layout.itemAt(i).widget()
                                if isinstance(child, QSpinBox):
                                    child.setValue(0)  # 将数量选择框重置为 0

    def confirm_sale(self):
        # if not self.cart:
        #     QMessageBox.warning(self, "警告", "购物车为空，无法确认销售！")
        #     return

        total = sum([self.db.get_product(pid)[2] * qty for pid, qty in self.cart.items()])
        total_qty = sum(self.cart.values())

        # 计算折扣
        discount = 1.0
        for threshold in sorted(self.discount_rules.keys(), reverse=True):
            if total_qty >= threshold:
                discount = self.discount_rules[threshold]
                break

        discount_total = total * discount

        # 将销售记录保存到数据库
        sale_id = self.db.execute_query("INSERT INTO sales (TOTAL, DISCOUNTED_TOTAL) VALUES (?, ?)", (total, discount_total)).lastrowid
        for pid, qty in self.cart.items():
            self.db.execute_query("INSERT INTO sale_items (SALE_ID, PRODUCT_ID, QUANTITY) VALUES (?, ?, ?)", (sale_id, pid, qty))

        QMessageBox.information(self, "销售确认", f"销售已确认！\n总价：{total:.2f}\n折扣价：{discount_total:.2f}")
        self.clear_cart()

    def init_ui(self):
        self.setWindowTitle('销售终端')
        self.setGeometry(100, 100, 1200, 800)  # 增大窗口尺寸

        # 使用类属性 self.main_layout
        # 折扣设置
        discount_layout = QHBoxLayout()
        self.discount_label = QLabel('当前折扣规则：')  # 修改：保留原有的 discount_label
        self.discount_input = QLineEdit()
        self.discount_input.setPlaceholderText('格式：数量:折扣, 如5:0.9,10:0.8')
        btn_add_discount = QPushButton('添加折扣')
        btn_add_discount.clicked.connect(self.add_discount)

        discount_layout.addWidget(self.discount_label)
        discount_layout.addWidget(self.discount_input)
        discount_layout.addWidget(btn_add_discount)

        # 新增：搜索功能
        search_layout = QHBoxLayout()
        self.search_input = QLineEdit()
        self.search_input.setPlaceholderText('输入商品名称搜索')
        btn_search = QPushButton('搜索')
        btn_search.clicked.connect(self.search_products)

        search_layout.addWidget(self.search_input)
        search_layout.addWidget(btn_search)

        # 购物车
        self.cart_table = QTableWidget()
        self.cart_table.setColumnCount(4)
        self.cart_table.setHorizontalHeaderLabels(['名称', '单价', '数量', '小计'])
        self.cart_table.setColumnWidth(0, 200)  # 增大商品名称列的宽度

        # 总计信息
        total_layout = QHBoxLayout()
        self.total_label = QLabel('总价：0.00')
        self.discount_label = QLabel('折扣价：0.00')  # 修改：保留原有的 discount_label
        self.discount_label.setStyleSheet("color: red;")  # 设置折扣价为红色
        btn_clear = QPushButton('清空购物车')
        btn_clear.clicked.connect(self.clear_cart)
        btn_confirm = QPushButton('确认销售')  # 新增：确认按钮
        btn_confirm.clicked.connect(self.confirm_sale)

        # 新增：总数量显示
        self.total_quantity_label = QLabel('总数量：0')
        total_layout.addWidget(self.total_quantity_label)  # 添加总数量显示
        total_layout.addWidget(self.total_label)
        total_layout.addWidget(self.discount_label)
        total_layout.addWidget(btn_clear)
        total_layout.addWidget(btn_confirm)
        self.setLayout(self.main_layout)  # 使用类属性 self.main_layout

        self.main_layout.addLayout(discount_layout)
        self.main_layout.addLayout(search_layout)  # 新增：添加搜索布局
        self.main_layout.addWidget(QLabel('商品列表'))
        self.main_layout.addWidget(self.cart_table)
        self.main_layout.addLayout(total_layout)

    # 修改：搜索商品逻辑
    def search_products(self):
        keyword = self.search_input.text().strip()
        if not keyword:
            self.load_products()  # 如果搜索框为空，重新加载所有商品
            return

        # 遍历商品列表，高亮展示匹配的商品名称
        for row in range(self.products_layout.rowCount()):
            for col in range(self.products_layout.columnCount()):
                item = self.products_layout.itemAtPosition(row, col)
                if item:
                    widget = item.widget()
                    if isinstance(widget, QWidget):
                        layout = widget.layout()
                        if layout:
                            for i in range(layout.count()):
                                child = layout.itemAt(i).widget()
                                if isinstance(child, QLabel) and child.text():  # 找到商品名称标签
                                    product_name = child.text()
                                    if keyword.lower() in product_name.lower():  # 模糊匹配
                                        # 高亮显示商品名称
                                        child.setStyleSheet("color: yellow; background-color: red;")
                                    else:
                                        # 恢复默认样式
                                        child.setStyleSheet("")

    def add_discount(self):
        """添加折扣规则"""
        discount_str = self.discount_input.text()
        try:
            for rule in discount_str.split(','):
                threshold, rate = map(float, rule.split(':'))
                self.db.update_discount(int(threshold), rate)  # 新增：保存到数据库
            self.load_discounts()  # 新增：重新加载折扣规则
            self.discount_input.clear()
            self.calculate_total()
        except Exception as e:
            QMessageBox.warning(self, "错误", f"折扣格式错误：{e}")

    def resizeEvent(self, event):
        """窗口大小变化时重新加载商品布局"""
        super().resizeEvent(event)
        self.load_products()


class StatisticsPage(QWidget):
    def __init__(self):
        super().__init__()
        self.db = Database()
        self.init_ui()

    def init_ui(self):
        self.setWindowTitle('销售统计')
        self.setGeometry(100, 100, 1200, 800)

        layout = QVBoxLayout()

        # 日期选择
        date_layout = QHBoxLayout()
        self.start_date = QDateEdit()
        self.start_date.setCalendarPopup(True)
        self.end_date = QDateEdit()
        self.end_date.setCalendarPopup(True)
        btn_query = QPushButton('查询')
        btn_query.clicked.connect(self.query_sales)

        # 设置默认日期为当前月份的第一天和最后一天
        current_date = QDate.currentDate()
        first_day_of_month = QDate(current_date.year(), current_date.month(), 1)
        last_day_of_month = first_day_of_month.addDays(current_date.daysInMonth() - 1)
        self.start_date.setDate(first_day_of_month)
        self.end_date.setDate(last_day_of_month)

        date_layout.addWidget(QLabel('开始日期:'))
        date_layout.addWidget(self.start_date)
        date_layout.addWidget(QLabel('结束日期:'))
        date_layout.addWidget(self.end_date)
        date_layout.addWidget(btn_query)

        # 销售记录表格
        self.sales_table = QTableWidget()
        self.sales_table.setColumnCount(4)
        self.sales_table.setHorizontalHeaderLabels(['销售ID', '总价', '折扣价', '时间'])

        # 产品统计表格
        self.product_stats_table = QTableWidget()
        self.product_stats_table.setColumnCount(3)
        self.product_stats_table.setHorizontalHeaderLabels(['产品名称', '销售数量', '销售额'])

        layout.addLayout(date_layout)
        layout.addWidget(QLabel('销售记录'))
        layout.addWidget(self.sales_table)
        layout.addWidget(QLabel('产品销售统计'))
        layout.addWidget(self.product_stats_table)

        self.setLayout(layout)

    def query_sales(self):
        start_date = self.start_date.date().toString("yyyy-MM-dd")
        end_date = self.end_date.date().toString("yyyy-MM-dd")

        # 查询销售记录
        sales_query = f"""
        SELECT s.ID, s.TOTAL, s.DISCOUNTED_TOTAL, s.TIMESTAMP
        FROM sales s
        WHERE s.TIMESTAMP BETWEEN ? AND ?
        ORDER BY s.TIMESTAMP DESC
        """
        sales_results = self.db.execute_query(sales_query, (start_date, end_date)).fetchall()

        self.sales_table.setRowCount(len(sales_results))
        for row, sale in enumerate(sales_results):
            for col, data in enumerate(sale):
                self.sales_table.setItem(row, col, QTableWidgetItem(str(data)))

        # 查询产品销售统计
        product_stats_query = f"""
        SELECT p.NAME, SUM(si.QUANTITY), SUM(si.QUANTITY * p.PRICE)
        FROM sale_items si
        JOIN products p ON si.PRODUCT_ID = p.ID
        JOIN sales s ON si.SALE_ID = s.ID
        WHERE s.TIMESTAMP BETWEEN ? AND ?
        GROUP BY p.NAME
        ORDER BY SUM(si.QUANTITY) DESC
        """
        product_stats_results = self.db.execute_query(product_stats_query, (start_date, end_date)).fetchall()

        self.product_stats_table.setRowCount(len(product_stats_results))
        for row, stats in enumerate(product_stats_results):
            for col, data in enumerate(stats):
                self.product_stats_table.setItem(row, col, QTableWidgetItem(str(data)))

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.setWindowTitle('冰淇淋管理系统')
        self.setGeometry(100, 100, 1024, 768)

        tab_widget = QTabWidget()
        self.product_manager = ProductManager()
        self.pos_system = PosSystem()
        self.statistics_page = StatisticsPage()  # 新增：统计页面
        tab_widget.addTab(self.product_manager, '商品管理')
        tab_widget.addTab(self.pos_system, '销售终端')
        tab_widget.addTab(self.statistics_page, '销售统计')  # 新增：添加统计页面

        # 页面切换时刷新数据
        tab_widget.currentChanged.connect(self.refresh_data)

        # 设置默认选中的标签页为销售终端
        tab_widget.setCurrentIndex(1)

        self.setCentralWidget(tab_widget)

        # 修改：将全屏展示改为最大化展示
        self.showMaximized()  # 替换原有的 showFullScreen()

    def refresh_data(self, index):
        """刷新当前标签页的数据"""
        if index == 0:  # 商品管理
            self.product_manager.load_data()
        elif index == 1:  # 销售终端
            self.pos_system.load_products()
        elif index == 2:  # 销售统计
            self.statistics_page.query_sales()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyleSheet("QLabel { font-size: 14pt; }")  # 全局增大字体
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())
